home *** CD-ROM | disk | FTP | other *** search
/ Commodore 64 Scene Diskmags Assortment / Commodore_CEE_Vol._1_Issue_05_1995_Jack_Vander_White_Disk_2_of_3_Side_B.d64 / program bit 7 < prev    next >
Text File  |  2023-02-26  |  18KB  |  305 lines

  1. NMI/IRQ
  2.  
  3. From : George Hug
  4.  
  5. Ed Bell writes:
  6.  
  7.  EB> The NMI/IRQ switch has nothing to do with locating the cartridge.
  8.  
  9.  EB> That switch is only used, as far as I know, for cP/M terminals.  I know that George Hug has said in the past that God never intended for the NMI to be used, but that is the way everyone has done things as far as I've ever seen.
  10.  
  11. I think the use of NMI got started with the VIC20 and C64 - because they had to process every incoming and outgoing bit individually, and had to have priority over the other stuff going on.  However, using the 6551 should allow you to just use the IRQ line like any other device. 
  12.  
  13. Well, in fact, the +4's microprocessor (the 8502, I think) doesn't even have an NMI pin, so everything runs off IRQ. But since the +4 has the built-in 6551, it works fine.
  14.  
  15. Of course at some point (14.4k maybe) I suspect you may start to push the limits of the system overall, even with a 6551.
  16.  
  17. The main theoretical problem with using the 6551 on the NMI line is that the NMI is edge-triggered and (of course) non-maskable.  When you read the status byte of the 6551, it re-enables the interrupt, so that some subsequent event can send you back into the NMI handler in a manner you are not expecting.  But there are ways around this - you just have to be careful writing the NMI handler.
  18.  
  19. --------------------------------- 
  20.  
  21. oVerflow ?
  22.  
  23. From : msmakela@sranje.tky.hut.fi
  24.  
  25. Ralph Mason <ralph.mason@liffe.com> writes:
  26.  
  27. Ralph> Can someone please give me a description of how the overflow flag is set by the ADC and SBC opcodes. There dose not seem to much information about this flag.  Any description or a Pseudo code description would be very helpful.
  28.  
  29. There are already some descriptions posted, but as they weren't complete, here's the one from the 64doc file (which is part of the X64 emulator project).  The whole file is available on the WWW, as http://www.hut.fi/{$de}msmakela/cbm/emul/x64/64doc.html.
  30.  
  31.             V   oVerflow flag
  32.  
  33.                 Like the Negative flag, this flag is intended to be
  34.                 used with 8-bit signed integer numbers. The flag will
  35.                 be affected by addition and subtraction, the
  36.                 instructions PLP, CLV and BIT, and the hardware signal
  37.                 -SO. Note that there is no SEV instruction, even
  38.                 though the MOS engineers loved to use East European
  39.                 abbreviations, like DDR (Deutsche Demokratische
  40.                 Republik vs. Data Direction Register). (The Russian
  41.                 abbreviation for their former trade association
  42.                 COMECON is SEV.) The -SO (Set Overflow) signal is
  43.                 available on some processors, at least the 6502, to
  44.                 set the V flag. This enables response to an I/O
  45.                 activity in equal or less than three clock cycles when
  46.                 using a BVC instruction branching to itself ($50 $FE).
  47.  
  48.                 The CLV instruction clears the V flag, and the PLP and
  49.                 BIT instructions copy the flag value from the bit 6 of
  50.                 the topmost stack entry or from memory.
  51.  
  52.                 After a binary addition or subtraction, the V flag
  53.                 will be set on a sign overflow, cleared otherwise.
  54.                 What is a sign overflow?  For instance, if you are
  55.                 trying to add 123 and 45 together, the result (168)
  56.                 does not fit in a 8-bit signed integer (upper limit
  57.                 127 and lower limit -128). Similarly, adding -123 to
  58.                 -45 causes the overflow, just like subtracting -45
  59.                 from 123 or 123 from -45 would do.
  60.  
  61.                 Like the N flag, the V flag will not be set as
  62.                 expected in the Decimal mode. Later in this document
  63.                 is a precise operation description.
  64.  
  65.                 A common misbelief is that the V flag could only be
  66.                 set by arithmetic operations, not cleared.
  67.  
  68. Well, that description wasn't as scientific as I thought. :-( So, here's some C code that sets the V flag after an addition:
  69.  
  70.         /* A +=s */
  71.  
  72.         t = A + s + C;
  73.         V = (t ^ A) & 128 && !((A ^ s) & 128);
  74.  
  75. If you want to see how the V flag is set in Decimal mode or with the ARR instruction ($6B), refer to the 64doc file.
  76.  
  77. ---- 
  78.  
  79. From: Asger Alstrup
  80.  
  81. The overflow flag is used to detect overflow in math when you calculate with 2nd complement numbers. 2nd complement is a technique used to re- present negative numbers in binary with the property that addition and subtraction can be performed as usual giving the correct result. 2nd complement is basically a clever encoding for the numbers:
  82.  
  83. 8-bit value     2nd complement interpretation
  84.   0                0
  85.   1                1
  86.   2                2
  87.  .. 127              127 128             -128 129             -127 ... 255               -1
  88.  
  89. To perform negation of a 2nd complement number, simply reverse all the bits in the number, and add 1 to the number as usual.
  90.  
  91. Given a number in 2nd complement, you can use this program to get the absolute value and sign in carry:
  92.  
  93.         cmp #$80
  94.         bcc positive
  95.         eor #$ff        ;Inverse all bits
  96.         adc #0          ;Carry is 1, so this will add 1
  97.         sec positive
  98.  
  99. where the carry will be set for negative numbers.
  100.  
  101. The other way is similar:
  102.  
  103.         bcc positive
  104.         eor #$ff        ;Inverse all bits
  105.         adc #0          ;Carry is 1, so this is will add 1 positive        
  106.  
  107. The overflow flag in the 6502 detects carrys from bit 6 to 7 for ADC,  and underflows for SBC.
  108.  
  109. I.e.:
  110.  
  111.         clc
  112.         lda #%0100 0000 ;Decimal 64
  113.         adc #%0100 0000 ;Decimal 64
  114.          will set the overflow flag, since a carry is generated from bit 6 to 7. The range for standard 2nd complement numbers in 8 bit is [-128,127], so the overflow flag detected that we can't represent 64+64=128 in 2nd complement.
  115.  
  116.         clc
  117.         lda #%1000 0000 ;-128
  118.         adc #%1111 1111 ;-1
  119.          will not set the overflow flag, but rather the carry flag.
  120.  
  121. Conclusion: The overflow flag is used in connection with the carry flag to establish whether the result of the addition/subtraction can be represented as a valid 2nd complement number in 8 bits.
  122.  
  123. Of course, the overflow flag is multiplexed and used in connection with the BIT command for a totally different purpose. Furthermore the 1541 uses a feature of the 6502 as a ingenious timinginstrument, where hardware changes the overflow bit when a byte is ready to be read/writen to the disk. This means that the command
  124.  
  125. loop    bvc loop
  126.  
  127. takes care of business.
  128.  
  129. ------------------------------- 
  130.  
  131. Subj : Direct threaded inner interpretors
  132.  
  133. From : brmcf@utkux1
  134.  
  135. Paul van Loon wrote:
  136.  
  137.   > Just a while back I did a FORTH on my C64. To get some speed out of it, I made it a subroutine threaded FORTH. Basically you compile an extra $20 (JSR) with every address you compile.
  138.         
  139.         Yeah: no matter how you swing it, the speed improvement in  subroutine threaded code is hard to argue with in a 6502 machine.  You  only pay an extra byte overhead per compiled word and since NEXT is a one  byte RTS instead of a two byte address (or execution token), you don't  start paying the extra space overhead until the fourth word compiled.
  140.  
  141. > The only problem I encountered was with FORTH words that used the return stack, e.g. DO ... LOOP. You have to manage the processor stack yourself to get this done, but this is a lot less efficient than a simple PHA or PLA.
  142.         
  143.         Exactly.  I found this too cumbersome.  Plus, if you aim to have a small number of concurent tasks in preemptive multitasking, you need to partiion the 256 byte hardware stack among the tasks; if you want to use it in a C64, you also loose whatever you allocate to the keyboard buffer -- say 16 bytes to keep it even.  If you want to have 4 tasks with pre-emptive multi-tasking, that would only be 30 addresses deep in each partition, which isn't a whole lot to play to many explicit R-stack games.  And at the speed of the 1MHz 6510 in a C64, anything but stack partitioning is too slow and memory consuming for pre-emptive multitasking.
  144.  
  145. > An alternative solution may be to have an extra 'RETURN' stack, that handles words like 'I'. If you want you can make 'R>' and '>R' to work on this stack or at the processor stack. But I think that using R> and >R to change the thread of execution is bad programming anyway.
  146.         
  147.         So do I, but since I elect to make the >R and R> the pseudo  R-stack that is used for I, I have a vested interest in not using the  'Rack' for flow of execution.
  148.  
  149.         Here's my approach: dedicate the X register to the current task  index.  The Y-register is used as a general index register, and is never  maintained across routines.  To make more space available on the zero  page, the top of stack is at the top of the stack: this costs about  four cycles for most low level words, but makes drop faster which often  makes up for it.  With a psuedo Return stack, you won't have to  manipulate the stack pointer, so only the task switcher needs to use TXS  and TSX, and the task switcher is 'aware' of which task is which, so it  can afford to use the X-register.
  150.  
  151.  
  152. PLUS   LDY OPNDX,X     ; zero-page
  153.         CLC
  154.         LDA TOS LO,Y    ; 16-bit
  155.         ADC SCND LO,Y   ; TOS LO+1
  156.         STA SCND LO,Y   ;
  157.         LDA TOS HI,Y    ; 16-bit
  158.         ADC SCND HI,Y   ; TOS- HI+1
  159.         STA SCND HI,Y   ; 
  160.         INY             ; seperated STACK LO & STACK HI permits One INC
  161.         STY OPNDX,Y     ; 
  162.         RTS
  163.  
  164.  
  165. TO R   LDY OPNDX,X
  166.         LDA TOS LO,Y
  167.         STA TEMP,X
  168.         LDA TOS HI,Y
  169.         INY
  170.         STY OPNDX,X
  171.         LDY RNDX,X
  172.         DEY
  173.         STA RACK-HI,Y
  174.         LDA TEMP,X
  175.         STA RACK LO,Y
  176.         STY RNDX,X
  177.         RTS
  178.  
  179.         Another point raised in the past couple of weeks comes to mind:  R@ will work here, but it will not be possible to fetch from the R stack  with a pointer, since RACK-LO nand RACK-HI do not live next to each other  in memory: they are allocated with either 128 or 256 bytes in each  stack partition, for 32 or 64 deep racks
  180.  
  181.         Up to 256 bytes total in each stack partition; 
  182.  
  183. ----------------------
  184. Boundary: xx00 address
  185.         RACK-HI#3       
  186.         RACK-HI#2
  187.         RACK-HI#1
  188.         RACK-HI#0 
  189.  
  190. ----------------------
  191. Boundary: either xx70 or xx00 address
  192.         RACK-LO#3       
  193.         RACK-HI#2
  194.         RACK-HI#1
  195.         RACK-HI#0 
  196.  
  197. ----------------------
  198. Boundary: xx00 address
  199.  
  200.         So for several reasons, I like the parts of the ANS standard that support independence from particular architectures.
  201.  
  202. ---------------------------------- 
  203.  
  204. Stable Rasters
  205.  
  206. From : A.BOOSE@LDB.han.de
  207.  
  208. LORDTYM@news.delphi.com (LORDTYM@DELPHI.COM) writes:
  209.  
  210. >The $d011 register is often referred to as the 'magic' register.
  211.  
  212. That's because you can control the status "Bad Line Condition" (BLC) with the 3 LSB of this register. Since the BLC triggers the video-counter (VC) and the row-counter (RC), you can get control of the 2 most important registers inside the VIC-II, deciding what data is displayed.
  213.  
  214. >I am beginning to think this is because nobody really knows the how or why it works.
  215.  
  216. Why not? Once you understood how the VIC-II displays a normal frame, you can easily explain any of what you called 'tricks'.
  217.  
  218. It seems that many people don't know how the VIC-II generates the 40*25 color screen or the 320*200 bitmap. Let me try to explain it...
  219.  
  220. The data the VIC displays in every dot-clock cycle has be fetched out of the system's RAM. It needs one byte per machine cycle (phi), so the C64's bus is split in phi1 when the VIC-II fetches its data and phi2 when the CPU is allowed to own the bus.
  221.  
  222. So all phi1 bandwidth (in the display area) is used to fetch data out of the char ROM/RAM. The problem is, the VIC-II needs additional information which characters/colors should be displayed. This information is fetched in any bad line in phi2 while the CPU is stopped. It's stored in a 40*12 bit char/col buffer called video-matrix.
  223.  
  224. The information which characters/colors should be displayed is supposed to be renewed every eight lines, so we need a BLC every eight lines. Therefore the status "BLC" is set if the screen is on and $30<=$d012<$f8 and the 3 LSB of $d011 and $d012 are equal. As $d012 counts the raster lines of a frame the 3 LSBs are equal any 8 lines and BLC is set. If BLC is set, the VIC-II generates phi2 DMA between X=0 and X=$13f.
  225.  
  226. The VIC-II knows what char to be displayed in the next phi1 cycle, but it also has to know which line of the char has to be displayed. Therefore it has a 3 bit wide row-counter (RC) which is set to 0 during BLC and(!!) X=0 and it counts up to 7 in the next 7 lines.
  227.  
  228. The video-counter supplies the address used to load the video-matrix during phi2 DMA. This counter is split in two 10 bit wide latches, the base (VCB) and the counter (VCC). Together with the 4 MSB of $d018 the VCC generates the VIC-II addresses during the phi2 DMA.
  229.  
  230. At the beginning of a frame VCB is cleared to 0. At X=0 of any line VCB is copied to VCC. VCC is counted up during the 40 display cycles. Only if RC is 7 and X=160, VCC is copied back to VCB (increasing the base).
  231.  
  232.  Technically that's all. All $d011-LSB-effects can be reduced as consequences of the statements above.
  233.  
  234. The key thing is to toggle the BLC status for several cycles ( = changing the the 3 LSB of $d011).
  235.  
  236. For example:
  237.  
  238. FLD: Change the 3 LSB of $d011 that they will never match with $d012. You will never get a BLC, nothing (VIC-II Address $3fff) is displayed.
  239.  
  240. Linecrunch: Let the 3 LSB of $d011 match $d012, but change the 3 LSB just before X=0 is reached. RC remains not set (7), no phi2 DMA to load the   video matrix, VCC is counted up by 40 and is copied to VCB on X=160. A   whole char line is crunched to one raster line.
  241.  
  242. FLI: After a 'normal' bad line let the 3 LSB of $d011 match $d012 after X=0. Due to BLC the VIC-II performs a phi2 DMA again, but the RC isn't set to 0. Changing $d018 from raster line to raster line will provide independent colors 1&2 on any raster line.
  243.  
  244. Note that the address/data drivers of the VIC-II remain off in phi2 during the first 3 BA=low cycles, the VIC reads $ff instead. The color code of the $ffs is the low nibble of the opcode coming right after the $d011 access that caused the forced DMA. So maybe the left 3 chars are lost.
  245.  
  246. >I wonder if some hacker didn't just stumble across the properties of this register. The actual code does not appear to be timed except to start at exactly the same place each time. The inc $d011 instructions appear to be the timers and will wait until the current raster line is finished.
  247.  
  248. Without seeing the context it's hard to say. But you can use $d011 to synchronize to the raster line, just set BLC during X=0..$13f, the 'forced' phi2 DMA will synchronize the CPU.
  249.  
  250. ----------------------------------- 
  251.  
  252. Sample 1x1 Scrolly Code
  253.  
  254. From : xmikex@eyrie.stanford.edu
  255.  
  256. Someone asked me for sample scrolly code, and then a few others asked me,  and so on, etc.  Anyways, I post sample code here so that a good thread will  emerge regarding scrolly coding techniques.  In other words, tear this  lame bit of code with your minds and make it better or simply walk us  through the best scrolly (monster scrolly) codes there are on C64/128.   It's up to you. 
  257.  
  258. (This code works on C64 and C128 (40 cols) with no modification).
  259.   org $3000 - a fake op...tells the assembler where we want the code to start
  260.             This fake op (pseudo op) can vary from assembler to assembler.
  261.  
  262.          LDA #$00  - ---------------------------------------------------
  263.          STA $FD   - All this is just so that we can do neato ind. index
  264.          LDA #$32  - addressing later.. ie., we are setting up the
  265.          STA $FE   - spot where scrolly text will be pulled from !
  266.   mainloop LDX #$C7  ; Prepare the scrolly register for a "hard right" bitloop  STX $D016 ; shove the "hard right" value into scrolly register
  267.          TXA       ; Preserve X by shoving onto A
  268.          PHA       ; and shove A into the stack (stack = temp storage)
  269.  
  270.              ;(we need to clear X cuz we gonna use it in a delay loop)
  271.              ;(if we don't introduce a delay, the text will scroll by
  272.              ; WAY TOO FAST to READ ! !   Incredible, this 1 Mhz bugger
  273.              ; machine of ours is, eh?) - delays not set in stone, play
  274.              ; with them :)  higher, lower, etc...
  275.  
  276.          LDX #$05     ; just a delay loop - ldx counted down by dex waitloop LDY #$FF     ; a delay loop within a delay loop wl2      DEY          ; decrement y in our delay looop
  277.          BNE wl2      ; keep counting y down until y = 0
  278.          DEX          ; decrement x in our top delay loop
  279.          BNE waitloop ; repeat the y loop until x = 0
  280.          PLA          ; grab X from the stack and shove it onto A
  281.          TAX          ; copy A into X (X = #$C7 from mainloop)
  282.          DEX          ; ok, now we countdown X
  283.          CPX #$BF     ; coarse scroll anyone?
  284.          BNE bitloop  ; back to bit pushing
  285.          LDX #$00     ; clear X rt       LDA $7C1,x   ; scroll the last screen line one char to the left
  286.          STA $7C0,x   ; we are shuffling one char into another
  287.          INX          ; increment X
  288.          CPX #$28     ; Hex $28 = Decimal 40 = width of VIC-II screen
  289.          BNE rt       ; still in coarse scroll?
  290.  
  291.          INC $FD      - here is where the indexing pays off, with
  292.          BNE TY       - these little lines all we gotta do is stick
  293.          INC $FE      - our scrolly-text data beginning (in this case) ty       LDY #$00     - at location $3200
  294.          LDA ($FD),Y  - :))))
  295.          STA $7E7     - shove the data into rightmost corner
  296.          JMP mainloop - let it scrooooolll, baby! (end of loop)
  297.  
  298.   $3200 is 12800 in decimal.  If I wanted to put some character data there, I could just poke it in, as follows:
  299.  
  300. POKE 12800,65 = A   at $3200 POKE 12801,66 = B   at $3201 etc
  301.  
  302. ------------------------------ 
  303.  
  304.  
  305.